package com.ruoyi.project.system.task;

import com.ruoyi.project.system.domain.ReminderLogs;
import com.ruoyi.project.system.domain.ReminderRules;
import com.ruoyi.project.system.domain.Tasks;
import com.ruoyi.project.system.service.IReminderLogsService;
import com.ruoyi.project.system.service.IReminderRulesService;
import com.ruoyi.project.system.service.ITaskPushService;
import com.ruoyi.project.system.service.ITasksService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 任务提醒定时任务
 * 
 * @author ruoyi
 * @date 2025-06-16
 */
@Component("taskReminderTask")
public class TaskReminderTask {

    private static final Logger log = LoggerFactory.getLogger(TaskReminderTask.class);

    @Autowired
    private IReminderRulesService reminderRulesService;

    @Autowired
    private ITaskPushService taskPushService;

    @Autowired
    private ITasksService tasksService;

    @Autowired
    private IReminderLogsService reminderLogsService;

    /**
     * 检查并推送到期的任务提醒
     * 定时执行：每分钟检查一次
     */
    public void checkAndPushReminders() {
        try {
            log.info("开始检查任务提醒");

            // 查询所有需要提醒的规则
            ReminderRules queryRule = new ReminderRules();
            List<ReminderRules> allRules = reminderRulesService.selectReminderRulesList(queryRule);

            if (allRules == null || allRules.isEmpty()) {
                log.info("没有找到任务提醒规则");
                return;
            }

            Date now = new Date();
            int reminderCount = 0;

            for (ReminderRules rule : allRules) {
                try {
                    // 检查是否到了提醒时间
                    if (rule.getNextTrigger() != null &&
                            (rule.getNextTrigger().before(now) ||
                                    rule.getNextTrigger().equals(now))) {

                        // 检查任务是否在有效期内
                        Tasks task = tasksService.selectTasksById(rule.getTaskId());
                        if (task == null) {
                            log.warn("任务不存在，跳过提醒，任务ID：{}", rule.getTaskId());
                            continue;
                        }

                        if (!isTaskValid(task)) {
                            log.info("任务不在有效期内，跳过提醒，任务ID：{}，任务标题：{}", task.getId(), task.getTitle());
                            continue;
                        }

                        // 推送提醒
                        boolean pushResult = taskPushService.pushTaskReminder(rule.getTaskId());

                        if (pushResult) {
                            log.info("任务提醒推送成功，任务ID：{}", rule.getTaskId());
                            reminderCount++;

                            // 更新下次提醒时间
                            Date nextTrigger = calculateNextTrigger(rule);
                            rule.setNextTrigger(nextTrigger);
                            rule.setLastTriggered(now);
                            rule.setUpdatedAt(now);

                            reminderRulesService.updateReminderRules(rule);
                            log.info("更新下次提醒时间，任务ID：{}，下次提醒：{}", rule.getTaskId(), nextTrigger);
                        } else {
                            log.error("任务提醒推送失败，任务ID：{}", rule.getTaskId());
                        }
                    }
                } catch (Exception e) {
                    log.error("处理任务提醒失败，任务ID：{}，错误：{}", rule.getTaskId(), e.getMessage(), e);
                }
            }

            log.info("任务提醒检查完成，共推送 {} 条提醒", reminderCount);
        } catch (Exception e) {
            log.error("任务提醒检查失败：{}", e.getMessage(), e);
        }
    }

    /**
     * 计算下次提醒时间（复用AppController中的逻辑）
     */
    private Date calculateNextTrigger(ReminderRules reminderRule) {
        Calendar now = Calendar.getInstance();
        Calendar next = Calendar.getInstance();

        // 设置时间
        Calendar timeCalendar = Calendar.getInstance();
        timeCalendar.setTime(reminderRule.getTimeOfDay());
        next.set(Calendar.HOUR_OF_DAY, timeCalendar.get(Calendar.HOUR_OF_DAY));
        next.set(Calendar.MINUTE, timeCalendar.get(Calendar.MINUTE));
        next.set(Calendar.SECOND, 0);
        next.set(Calendar.MILLISECOND, 0);

        String frequency = reminderRule.getFrequency();

        switch (frequency) {
            case "immediate":
                // 立即推送：不再重复，返回null或设为很远的将来
                next.add(Calendar.YEAR, 100); // 设为100年后，表示不再重复
                break;
            case "daily":
                // 每日提醒：下一天
                next.add(Calendar.DAY_OF_YEAR, 1);
                break;

            case "weekly":
                if (reminderRule.getWeeklyDays() != null) {
                    // 解析周几，格式如"[1,3,5]"或"[4]"
                    String weeklyDays = reminderRule.getWeeklyDays();
                    String[] days = weeklyDays.replaceAll("[\\[\\]]", "").split(",");

                    int nearestDay = findNearestWeekDay(now, Integer.parseInt(days[0].trim()));
                    for (String dayStr : days) {
                        int dayOfWeek = Integer.parseInt(dayStr.trim());
                        int candidateDay = findNearestWeekDay(now, dayOfWeek);
                        if (candidateDay < nearestDay) {
                            nearestDay = candidateDay;
                        }
                    }

                    next.add(Calendar.DAY_OF_YEAR, nearestDay);
                } else {
                    // 默认下周同一天
                    next.add(Calendar.WEEK_OF_YEAR, 1);
                }
                break;

            case "monthly":
                if (reminderRule.getMonthlyDays() != null) {
                    // 解析每月的哪几天，格式如"[1,15]"
                    String monthlyDays = reminderRule.getMonthlyDays();
                    String[] days = monthlyDays.replaceAll("[\\[\\]]", "").split(",");

                    int currentDay = now.get(Calendar.DAY_OF_MONTH);
                    boolean foundThisMonth = false;

                    for (String dayStr : days) {
                        int targetDay = Integer.parseInt(dayStr.trim());
                        if (targetDay > currentDay) {
                            next.set(Calendar.DAY_OF_MONTH, targetDay);
                            foundThisMonth = true;
                            break;
                        }
                    }

                    if (!foundThisMonth) {
                        // 下个月的第一个日期
                        next.add(Calendar.MONTH, 1);
                        int firstDay = Integer.parseInt(days[0].trim());
                        next.set(Calendar.DAY_OF_MONTH, firstDay);
                    }
                } else {
                    // 默认下个月同一天
                    next.add(Calendar.MONTH, 1);
                }
                break;

            case "yearly":
                // 默认下一年同一时间
                next.add(Calendar.YEAR, 1);
                break;

            default:
                // 默认明天同一时间
                next.add(Calendar.DAY_OF_YEAR, 1);
                break;
        }

        return next.getTime();
    }

    /**
     * 找到最近的指定星期几距离今天的天数
     */
    private int findNearestWeekDay(Calendar now, int targetDayOfWeek) {
        int currentDayOfWeek = now.get(Calendar.DAY_OF_WEEK);
        int daysToAdd = targetDayOfWeek - currentDayOfWeek;

        if (daysToAdd <= 0) {
            daysToAdd += 7; // 下周
        }

        return daysToAdd;
    }

    /**
     * 检查任务是否在有效期内
     * 
     * @param task 任务对象
     * @return true-有效期内，false-无效期内
     */
    private boolean isTaskValid(Tasks task) {
        Date now = new Date();

        // 检查任务是否激活
        if (task.getIsActive() == null || task.getIsActive() != 1) {
            log.debug("任务未激活，任务ID：{}", task.getId());
            return false;
        }

        // 检查生效开始时间（为空表示立即生效）
        if (task.getEffectiveStart() != null && now.before(task.getEffectiveStart())) {
            log.debug("任务尚未到生效开始时间，任务ID：{}，开始时间：{}，当前时间：{}",
                    task.getId(), task.getEffectiveStart(), now);
            return false;
        }

        // 检查生效结束时间（为空表示永久有效）
        if (task.getEffectiveEnd() != null && now.after(task.getEffectiveEnd())) {
            log.debug("任务已超过生效结束时间，任务ID：{}，结束时间：{}，当前时间：{}",
                    task.getId(), task.getEffectiveEnd(), now);
            return false;
        }

        return true;
    }
}